package com.example.skyline.service.impl;

import com.example.skyline.service.VideoStreamService;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Service  // 声明为Spring服务组件
public class VideoStreamServiceImpl implements VideoStreamService {
    private final ExecutorService executorService = Executors.newFixedThreadPool(9); // 创建固定大小为9的线程池
    private final String url = "http://localhost:8080";
    // 保存活跃的视频转码器，key为视频ID，value为对应的FFmpeg录制器
    private final Map<Long, FFmpegFrameRecorder> activeRecorders = new ConcurrentHashMap<>();

    // 保存视频流数据缓冲区，key为视频ID，value为字节输出流
    private final Map<Long, ByteArrayOutputStream> streamBuffers = new ConcurrentHashMap<>();

    //  保存视频保存目录
    private final String videoSaveDirectory = "D:\\BaiduNetdiskDownload\\video";


    /**
     * 将RTSP流转码为FLV格式
     * @param videoId 视频唯一标识符
     * @param rtspUrl RTSP流地址
     * @return FLV流的HTTP访问路径
     */
    public synchronized String convertRtspToFlv(Long videoId, String rtspUrl) throws FFmpegFrameRecorder.Exception, FFmpegFrameGrabber.Exception {
        // 检查是否已经有该视频的转码器在运行，避免重复创建
        if (activeRecorders.containsKey(videoId)) {
            return url+"/video/stream/" + videoId;  // 返回已有的流地址
        }

        // 创建RTSP流抓取器
        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(rtspUrl);
        grabber.setOption("rtsp_transport", "tcp");  // 使用TCP协议传输，更稳定
        grabber.setFrameRate(25);                    // 设置帧率为25fps
        grabber.setVideoBitrate(1500000);            // 设置视频比特率为1.5Mbps
        grabber.start();                             // 启动抓取器

        // 创建字节输出流作为FLV数据的缓冲区
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        streamBuffers.put(videoId, outputStream);    // 将缓冲区存入Map

        // 创建FLV录制器，参数与抓取器保持一致
        FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(
                outputStream,                           // 输出到字节流
                grabber.getImageWidth(),                // 视频宽度
                grabber.getImageHeight(),               // 视频高度
                grabber.getAudioChannels()              // 音频通道数
        );

        // 设置FLV格式参数
        recorder.setFormat("flv");                  // 输出格式为FLV
        recorder.setFrameRate(grabber.getFrameRate());  // 设置帧率
        recorder.setVideoBitrate(grabber.getVideoBitrate()); // 设置视频比特率
        recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264); // H.264编码
        recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);  // AAC音频编码
        recorder.setVideoOption("tune", "zerolatency");  // 零延迟模式
        recorder.setVideoOption("preset", "ultrafast"); // 最快编码速度
        recorder.setGopSize(25); // 1秒一个关键帧（25fps）
        recorder.setMaxDelay(0); // 最小化封装延迟
        recorder.setFrameRate(25); // 确保帧率匹配
        recorder.setVideoOption("openh264:profile", "baseline");  // 基线Profile（低复杂度）
        recorder.setVideoOption("openh264:max_nal_size", "0");    // 禁用NAL单元分片
        recorder.setVideoOption("openh264:multiple_thread", "0"); // 禁用多线程（减少调度开销）
        recorder.start();                          // 启动录制器

        // 将录制器存入Map
        activeRecorders.put(videoId, recorder);

        // 启动转码线程
        executorService.submit(() -> {
            try {

                // 持续转码直到该视频被停止
                while (activeRecorders.containsKey(videoId)) {

                  /*  //  抓取并录制帧
                    Frame  frame = grabber.grab();
                    if (frame != null){*/
                    recorder.record(grabber.grab());  // 抓取并录制帧
                        /*fileRecorder.record(frame);//  录制帧
                    }

                    fileRecorder.stop();
                    fileRecorder.close();*/
                }
            } catch (Exception e) {
                // 忽略正常停止导致的异常
                if (!activeRecorders.containsKey(videoId)) {
                    return;
                }
                e.printStackTrace();
            } finally {
                try {
                    // 释放资源
                    grabber.close();    // 关闭抓取器
                    recorder.close();   // 关闭录制器
                    outputStream.close(); // 关闭输出流
                } catch (Exception e) {
                    e.printStackTrace();
                }
                // 从Map中移除
                activeRecorders.remove(videoId);
                streamBuffers.remove(videoId);
            }
        });  // 启动线程

        return url+"/video/stream/" + videoId;  // 返回FLV流地址
    }

    /**
     * 创建保存视频的目录
     */
    private void createSaveDirectory() throws IOException {
        // 检查保存目录是否存在，不存在则创建
        Path path = Paths.get(videoSaveDirectory);
        // 如果目录不存在，则创建它
        if (!Files.exists(path)) {
            Files.createDirectories(path);
        }
    }

    /**
     * 停止指定视频的FLV转码
     * @param videoId 要停止的视频ID
     */
    public void stopFlvStream(Long videoId) {
        // 检查是否有该视频的转码器
        if (activeRecorders.containsKey(videoId)) {
            FFmpegFrameRecorder recorder = activeRecorders.get(videoId);
            try {
                recorder.stop();    // 停止录制
                recorder.close();   // 关闭录制器
            } catch (Exception e) {
                e.printStackTrace();
            }
            // 从Map中移除
            activeRecorders.remove(videoId);
            streamBuffers.remove(videoId);
        }
    }

    /**
     * 获取指定视频的FLV流数据
     * @param videoId 视频ID
     * @return FLV格式的字节数组
     */
    public byte[] getFlvData(Long videoId) {
        ByteArrayOutputStream buffer = streamBuffers.get(videoId);
        return buffer != null ? buffer.toByteArray() : new byte[0];  // 返回数据或空数组
    }
}